package com.itheima.app.interceptor;

import com.alibaba.fastjson.JSON;
import com.itheima.domain.db.User;
import com.itheima.util.ConstantUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.Duration;

//开发拦截器
@Component
public class TokenInterceptor implements HandlerInterceptor {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    //进入controller之前(token的校验)
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //1. 判断请求头中是否有token,如果没有,直接无权限方法
        String token = request.getHeader("Authorization");
        if (StringUtils.isEmpty(token)) {
            response.setStatus(401);//无权访问
            return false;//禁止通行
        }
        //2. 从redis中未查到token或者查到的有问题
        User user = getUserFromToken(token);
        if (user == null) {
            response.setStatus(401);//无权访问
            return false;//禁止通行
        }
        //3. 将user信息存入threadLocal
        UserHolder.setUser(user);
        return true;//放行请求
    }

    //请求离开服务器之前(threadLocal的清理)
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        UserHolder.removeUser();
    }

    //根据token获取用户信息
    private User getUserFromToken(String token) {
        try {
            //1. 从redis中查询token
            String json = stringRedisTemplate.opsForValue().get(ConstantUtil.USER_TOKEN + token);

            //2. 将json转换成User对象
            User user = JSON.parseObject(json, User.class);

            //3. redis进行续期
            stringRedisTemplate.opsForValue().set(ConstantUtil.USER_TOKEN + token, json, Duration.ofDays(7));
            //4. 将user对象返回
            return user;
        } catch (Exception e) {
            //存在异常
            return null;
        }
    }
}